﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Net;
using System.Threading;
using System.IO;
using System.Xml;
using IApplication;
using IApplication.Net.Feeds;

namespace RssBar
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// wysokość strefy roboczej
        /// </summary>
        public static double WorkAreaHeight = -1;
        /// <summary>
        /// Aktualny indeks wiadomości w liście
        /// </summary>
        private int msgIndex = -1;
        /// <summary>
        /// Adres kanału Rss
        /// </summary>
        private string channelUrl = string.Empty;

        /// <summary>
        /// Lista wiadomości
        /// </summary>
        private List<RssMessage> messages = new List<RssMessage>();

        /// <summary>
        /// Czy okno konfiguracji jest otwarte
        /// </summary>
        private bool IsConfigWindowOpen = false;

        public MainWindow()
        {
            InitializeComponent();

            //wczytaj historię
            this.messages = Configuration.HistoryList as List<RssMessage>;

            WorkAreaHeight = this.Grid.Height + this.BorderThickness.Top + this.BorderThickness.Bottom;

            SetWindowPositionInWorkArea(WorkArea.AppWorkArea);

            //uruchom timer
            DispatcherTimer updateMessagesTimer = new DispatcherTimer();
            updateMessagesTimer.Interval = new TimeSpan(0, 0, 5); //5 sek
            updateMessagesTimer.Tick += new EventHandler(updateMessagesTimer_Tick);
            updateMessagesTimer.Start();

            //download messages 
            DispatcherTimer downloadTimer = new DispatcherTimer();
            downloadTimer.Interval = new TimeSpan(0, 0, 10); //10 sek
            downloadTimer.Tick += new EventHandler((object snd, EventArgs e) =>
            {
                //TODO: Pobierz wiadomości i połącz listy wiadomości
                ReadMessages();
            });
            downloadTimer.Start();

            //czytaj wszystkie wiadomości
            ReadMessages();

            //odśwież interfejs
            ReloadUI();
        }

        void updateMessagesTimer_Tick(object sender, EventArgs e)
        {
            //sprawdź strefę roboczą
            Rect workArea = SystemParameters.WorkArea;
            if (workArea.Top == WorkArea.OldWorkArea.Top)
            {
                //ustaw strefę roboczą aplikacji
                if (RssBar.WorkArea.SetArea(36, ref WorkArea.AppWorkArea))
                {
                    SetWindowPositionInWorkArea(WorkArea.AppWorkArea);
                }
            }

            //wyświetl wiadomość
            if (messages != null && (messages.Count - 1) > -1)
            {
                if (msgIndex >= messages.Count - 1)
                    msgIndex = 0;
                else
                    msgIndex++;

                String title = messages[msgIndex].Details.Title;
                SetLink(msgIndex,
                    title,
                    messages[msgIndex].Details.Description,
                    messages[msgIndex].Details.Link.AbsoluteUri,
                    messages[msgIndex].Details.PubDate.ToLocalTime().ToString(),
                    false,
                    messages[msgIndex].IsVisited);
            }
        }

        /// <summary>
        /// Łączy aktualnie pobraną listę wiadomości wraz z właściwościami z listą "messages"
        /// </summary>
        private void ReadMessages()
        {
            try
            {
                FeedReader rr = new FeedReader(new Uri(Configuration.ChannelAddress));
                var tmp = new List<RssMessage>();
                foreach (var item in rr.Channel.Items)
                {
                    RssMessage rmsg = new RssMessage();
                    rmsg.Details = item;
                    tmp.Add(rmsg);
                }

                //ustaw ikonkę kanału
                var image = rr.Channel.Image;
                if (image != null)
                {
                    ImageSource iconSrc = Helpers.GetImageSourceFromUrl(image.Url.AbsoluteUri, this.channelIconInfo);
                    if (iconSrc != null)
                    {
                        this.channelIconInfo.Source = iconSrc;
                    }
                }

                //adres kanału rss
                if (rr.Channel.Link != null)
                    this.channelUrl = rr.Channel.Link.AbsoluteUri;

                //Tooltip
                Run title = new Run();
                title.FontStyle = FontStyles.Italic;
                title.FontWeight = FontWeights.Bold;
                title.Text = rr.Channel.Title;
                Run message = new Run();
                message.Text = rr.Channel.Description;
                Run copyright = new Run();
                copyright.Text = rr.Channel.Copyright;
                Helpers.ShowTooltip(control: channelIconInfo, runs: new Run[] { title, message, copyright });

                //...
                foreach (var entry in tmp)
                {
                    for (int i = 0; i < messages.Count; i++)
                    {
                        if (messages[i].Details.Link != entry.Details.Link)
                        {
                            entry.IsVisited = false;
                        }
                        else if (messages[i].Details.Link == entry.Details.Link &&
                            messages[i].IsVisited == true)
                        {
                            entry.IsVisited = true;
                            break;
                        }
                    }
                }

                if (tmp.Count > 0)
                {
                    messages = tmp as List<RssMessage>;
                }
            }
            catch (Exception e)
            {
                Logger.Write(LoggerEventType.Error, e.Message, "[MainWindow.ReadMessages] Błąd podczas odczytywania wiadomości!");
            }
        }

        private void SetWindowPositionInWorkArea(WorkArea.RECT workArea)
        {
            //ustawienie pozycji okna
            this.Left = workArea.Left;
            this.Top = workArea.Top - WorkAreaHeight;

            //dopasowanie rozmiaru okna do sterfy roboczej
            this.Width = workArea.Width;
        }

        private object SetLink(int msgIndex, string title, string description, string link, string pubDate, bool msgMenu, bool visited)
        {
            Hyperlink hyperlink = new Hyperlink();
            try
            {
                hyperlink.NavigateUri = new System.Uri(link); //dodaj odnośnik
            }
            catch (UriFormatException ufe)
            {
                Logger.Write(LoggerEventType.Warning, ufe.Message, "[MainWindow.SetLink] Odnosnik \"{0}\" jest nie poprawny!", link);
            }
            catch (ArgumentNullException ane)
            {
                Logger.Write(LoggerEventType.Warning, ane.Message, "[MainWindow.SetLink] Argument \"link\" nie moze byc pusty!");
            }

            //Tooltip
            Run rtitle = new Run();
            rtitle.FontStyle = FontStyles.Italic;
            rtitle.FontWeight = FontWeights.Bold;
            rtitle.Text = title;
            Run rmessage = new Run();
            rmessage.Text = description;
            Run rpubDate = new Run();
            rpubDate.FontStyle = FontStyles.Italic;
            rpubDate.Text = pubDate;
            Helpers.ShowTooltip(control: hyperlink, runs: new Run[] { rtitle, rmessage, rpubDate });

            //kliknięcie w link
            hyperlink.RequestNavigate += ((object snd, RequestNavigateEventArgs rnea) =>
                {
                    System.Diagnostics.Process.Start(rnea.Uri.ToString());
                    messages[msgIndex].IsVisited = true;

                    //zapisz historię
                    QuickSaveHistoryList();
                });

            double avaible = .0;
            if (!msgMenu)
            {
                avaible = this.linkLabel.RenderSize.Width - 10;
                hyperlink.Inlines.Add(Helpers.FitText(this.linkLabel, title, "...", avaible)); //dodaj wiadomość

                linkLabel.Content = hyperlink; //dodaj hyperlink do kontrolki

                //animacja
                DoubleAnimation da = new DoubleAnimation();
                da.From = 0;
                da.To = 100;
                da.Duration = new Duration(TimeSpan.FromSeconds(1.5));

                //rozpoczęcie animacji na właściwości kontrolki
                linkLabel.BeginAnimation(Label.HeightProperty, da);

                return linkLabel;
            }
            else
            {
                MenuItem menuItem = new MenuItem();

                StackPanel menuRoot = new StackPanel();
                menuRoot.Height = 24;
                menuRoot.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                menuRoot.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                menuRoot.Orientation = Orientation.Horizontal;

                Label linkLabel = new Label();
                linkLabel.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                linkLabel.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
                linkLabel.Height = 24;
                linkLabel.FontSize = 12;
                linkLabel.Content = hyperlink;

                //menuRoot.Children.Add(icon);
                menuRoot.Children.Add(linkLabel);

                System.Windows.Controls.Image icon = new Image();
                icon.Height = 24;
                icon.Stretch = Stretch.Fill;
                icon.Width = 24;
                icon.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                if (!visited)
                    icon.Source = Helpers.GetImageSourceFromApp("Images/new-message-icon.png");
                else
                    icon.Source = Helpers.GetImageSourceFromApp("Images/message-already-read-icon.png");
                menuItem.Icon = icon;

                menuItem.Header = menuRoot; //dodaj do pola menu własny panel

                avaible = 200;
                hyperlink.Inlines.Add(Helpers.FitText(linkLabel, title, "...", avaible)); //dodaj wiadomość

                System.Windows.Controls.Image oldImage = icon;
                menuItem.MouseEnter += ((object snd, MouseEventArgs e) =>
                {
                    MenuItem mItem = snd as MenuItem;
                    System.Windows.Controls.Image ic = new Image();
                    ic.Height = 24;
                    ic.Stretch = Stretch.Fill;
                    ic.Width = 24;
                    ic.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                    ic.Source = Helpers.GetImageSourceFromApp("Images/search_24.png");
                    mItem.Icon = ic;
                });

                menuItem.MouseLeave += ((object snd, MouseEventArgs e) =>
                    {
                        (snd as MenuItem).Icon = oldImage;
                    });

                return menuItem;
            }
        }

        private void btnMessages_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                System.Windows.Controls.ContextMenu cm = new ContextMenu();

                for (int i = 0; i < messages.Count; i++)
                {
                    RssMessage entry = messages[i];
                    cm.Items.Add(SetLink(i, entry.Details.Title,
                        entry.Details.Description,
                        entry.Details.Link.AbsoluteUri,
                        entry.Details.PubDate.ToLocalTime().ToString(), 
                        true, 
                        entry.IsVisited));
                }

                cm.PlacementTarget = sender as UIElement;
                cm.IsOpen = true;
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            notifyIcon.Dispose();
        }

        private void btnInfo_MouseDown(object sender, MouseButtonEventArgs e)
        {
            AboutWindow aboutWin = new AboutWindow();
            aboutWin.ShowDialog();
        }

        private void channelIconInfo_MouseDown(object sender, MouseButtonEventArgs e)
        {
            System.Diagnostics.Process.Start(this.channelUrl);
        }

        /// <summary>
        /// Szybki zapis historii wiadomości
        /// </summary>
        private void QuickSaveHistoryList()
        {
            Configuration.HistoryList = this.messages;
            Configuration.Save();
        }

        private void btnConfig_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ShowConfigDialog();
        }

        private void ShowConfigDialog()
        {
            if (IsConfigWindowOpen)
                return;

            IsConfigWindowOpen = true;
            OptionsWindow optWindow = new OptionsWindow(new OptionsContentService());
            optWindow.ShowDialog();
            if (optWindow.Status == OptionStatus.Finished)
            {
                ReloadUI();
            }
            IsConfigWindowOpen = false;
        }

        private void ReloadUI()
        {
            //okno zawsze na wierzchu
            this.Topmost = Configuration.TopMost;

            //pasek zadań
            this.ShowInTaskbar = Configuration.ShowInTaskbar;

            //czy ma byc widoczna ikona w zasobniku
            object value = Configuration.ShowInTray;
            bool flag = false;
            if (value is bool)
            {
                flag = (bool)value;
            }
            else if (value is bool?)
            {
                bool? nullable = (bool?)value;
                flag = nullable.HasValue ? nullable.Value : false;
            }
            this.notifyIcon.Visibility = (flag ? Visibility.Visible : Visibility.Collapsed);
        }

        private void tmiOptions_Click(object sender, RoutedEventArgs e)
        {
            ShowConfigDialog();
        }

        private void tmiClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            notifyIcon.Dispose();
        }
    }
}
